﻿using DotNetty.Transport.Channels;
using System;

namespace DotNetty.Wraper
{
    abstract class BaseTcpSocketClient<TSocketClient, TData> : IBaseTcpSocketClient, IChannelEvent
        where TSocketClient : class, IBaseTcpSocketClient
    {
#if !NET45
        protected static System.Diagnostics.DiagnosticListener listener = new System.Diagnostics.DiagnosticListener(DiagnosticListenerExtensions.DiagnosticListenerName);
#endif
        protected TcpSocketCientEvent<TSocketClient, TData> _clientEvent { get; }
        protected IChannel _channel { get; set; }

        public BaseTcpSocketClient(string ip, int port, TcpSocketCientEvent<TSocketClient, TData> clientEvent)
        {
            Ip = ip;
            Port = port;
            _clientEvent = clientEvent;
        }
        protected void PackException(Action action)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                _clientEvent.OnException?.Invoke(ex);
            }
        }

        public string Ip { get; }

        public int Port { get; }

        public void SetChannel(IChannel channel)
        {
            if (_channel == null || !_channel.Active)
                _channel = channel;
        }
        public System.Action BeforeClose { get; set; }
        public void Close()
        {
            BeforeClose?.Invoke();
            _channel?.CloseAsync();
            AfterClose?.Invoke();
        } 
        public System.Action AfterClose { get; set; }
        public void OnChannelRegistered(IChannel channel)
        {
            SetChannel(channel);
            _clientEvent.OnChannelRegistered?.Invoke(this as TSocketClient, channel);
        }
        public void OnChannelUnregistered(IChannel channel)
        {
            _clientEvent.OnChannelUnregistered?.Invoke(this as TSocketClient, channel);
        }

        public virtual void OnChannelActive(IChannelHandlerContext ctx)
        {
            SetChannel(ctx.Channel);

            _clientEvent.OnClientStarted?.Invoke(this as TSocketClient);
        }

        public void OnChannelInactive(IChannel channel)
        {
            _clientEvent.OnClientClose?.Invoke(this as TSocketClient);
        }

        public void OnException(IChannel channel, Exception exception)
        {
            _clientEvent.OnException?.Invoke(exception);
            //Close(null);
#if !NET45
            listener.ClientException(exception);
#endif
        }

        public abstract void OnChannelReceive(IChannelHandlerContext ctx, object msg);
    }
}
